home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / ted5.zip / IGRABSRC.ZIP / LBMLOAD.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  13KB  |  571 lines

  1. /////////////////////////////////////////////////////////////
  2. /*
  3. ** ILBM file loader by John Romero (C) 1991 Id Software
  4. **
  5. ** Loads and decompresses an ILBM-format file to the
  6. ** screen in either CGA, EGA or MCGA -- compressed or
  7. ** or unpacked!
  8. **
  9. ** Merely pass the filename of the image to LoadLBM
  10. ** and sit back! The proper graphics mode is initialized
  11. ** and the screen (or brush) is loaded and displayed!
  12. **
  13. */
  14. /////////////////////////////////////////////////////////////
  15. #include "igrab.h"
  16. #pragma hdrstop
  17.  
  18. //
  19. // LBMload PROTOs
  20. //
  21.  
  22. void GetChunkID(char huge *buffer,char *tempstr);
  23. int  NextChunkID(char huge *buffer);
  24. void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes);
  25. void huge *SetupLBM(char *filename);
  26. void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem);
  27. void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem);
  28. void Do_MCGA_Screen(char huge *buffer,char compress,int width,int height,char huge *scrnmem);
  29.  
  30. char typestr[5],huge *startbuff;
  31.  
  32.  
  33. //
  34. // Here goes!
  35. //
  36. char huge *LoadLBM(char *filename,LBMtype *thelbm)
  37. {
  38.  char huge *buffer,huge *cmap,huge *scrnmem;
  39.  char planes,tempstr[5],compress;
  40.  unsigned handle,width,height;
  41.  
  42.   if((buffer = SetupLBM(filename))==NULL) errout("LBMLOAD error");
  43.  
  44.   /*
  45.   ** Need to get BMHD info, like:
  46.   ** - screen width, height
  47.   ** - # of bitplanes
  48.   ** - compression flag (YES/NO)
  49.   */
  50.  
  51.   width  = (*(buffer+9)&0xFF)+(*(buffer+8)*256);
  52.   height = (*(buffer+11)&0xFF)+(*(buffer+10)*256);
  53.   planes = *(buffer+16);
  54.   if (buffer[17])
  55.     {
  56.      char string[]="The ILBM screen '";
  57.  
  58.      strcat(string,filename);
  59.      strcat(string,"' is in STENCIL mode!\nGo back into DeluxePaint and turn it off!");
  60.      errout(string);
  61.     }
  62.   compress = *(buffer+18);
  63.  
  64.   thelbm->width=width;    // fill the struct
  65.   thelbm->height=height;
  66.   thelbm->planes=planes;
  67.  
  68.   if ((scrnmem=(char huge *)farmalloc((long)(width/8)*height*planes))==NULL)
  69.     {
  70.      char str[100]="Not enough memory for loading the ILBM screen '";
  71.  
  72.      strcat(str,filename);
  73.      strcat(str,"'!");
  74.      errout(str);
  75.     }
  76.  
  77.   /*
  78.   ** Find the CMAP chunk so I can remap the registers...
  79.   */
  80.  
  81.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  82.   tempstr[4]=0;
  83.   while (strcmp(tempstr,"CMAP")!=0)
  84.      {
  85.       buffer += NextChunkID(buffer);
  86.       movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  87.      }
  88.  
  89.   cmap = buffer+8;
  90.  
  91.   /*
  92.   ** Now, find the BODY chunk...
  93.   */
  94.  
  95.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  96.   while (strcmp(tempstr,"BODY")!=0)
  97.      {
  98.       buffer += NextChunkID(buffer);
  99.       movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  100.      }
  101.  
  102.   /*
  103.   ** Found the BODY chunk! Here we go!
  104.   */
  105.  
  106.   buffer += 8; /* point to actual data */
  107.  
  108.   switch (planes)
  109.     {
  110.       case 2: Do_CGA_Screen(buffer,compress,planes,width,height,scrnmem);
  111.           break;
  112.       case 4: Do_EGA_Screen(buffer,compress,planes,width,height,scrnmem);
  113.           break;
  114.       case 8: {
  115.            unsigned int i;
  116.  
  117.            if (!noshow)
  118.          {
  119.           for (i=0;i<0x300;i++) (unsigned char)*cmap++ >>= 2;
  120.  
  121.           cmap -= 0x300; // reset to beginning again
  122.  
  123.           _BX = 0;
  124.           _CX = 0x100;
  125.           _ES = FP_SEG(cmap);
  126.           _DX = FP_OFF(cmap);
  127.           _AX = 0x1012;
  128.           geninterrupt(0x10);
  129.          }
  130.  
  131.            Do_MCGA_Screen(buffer,compress,width,height,scrnmem);
  132.  
  133.            break;
  134.           }
  135.  
  136.       default: {
  137.         char msg[80]="This screen has ",temp[10];
  138.  
  139.         itoa(planes,temp,10);
  140.         strcat(msg,temp);
  141.         strcat(msg," bitplanes. I don't unnerstand that sorta stuff.");
  142.         errout(msg);
  143.            }
  144.     }
  145.   farfree((void far *)startbuff);
  146.  return scrnmem;
  147. }
  148.  
  149.  
  150. void huge *SetupLBM(char *filename)
  151. {
  152.  long filesize;
  153.  int handle;
  154.  char huge *buffer;
  155.  char tempstr[64],errst[120];
  156.  
  157.  
  158.  
  159.  filesize = filelen(filename);
  160.  buffer = startbuff = (char huge *)farmalloc(filesize);
  161.  if (buffer==NULL)
  162.  {
  163.    strcpy(errst,"Not enough memory to load ILBM file! Size=");
  164.    ltoa(filesize,tempstr,10);
  165.    strcat(errst,tempstr);
  166.    errout(errst);
  167.  }
  168.  
  169.  strupr(filename);
  170.  if (strstr(filename,".")==NULL)
  171.     strcat(filename,".LBM");
  172.  
  173.  if (access(filename,0))
  174.    {
  175.     char msg[80]="The ILBM file '";
  176.  
  177.     strcat(msg,filename);
  178.     strcat(msg,"' doesn't exist!");
  179.     errout(msg);
  180.    }
  181.  
  182.  LoadFile(filename,buffer,0,0);
  183.  
  184.  GetChunkID(buffer,tempstr);
  185.  if (strcmp(tempstr,"FORM")!=0)
  186.    errout("This isn't an ILBM FORM format file!");
  187.  
  188.   /*
  189.   ** point past the FORM chunk
  190.   ** and see if this really IS
  191.   ** and ILBM file
  192.   */
  193.  
  194.   buffer += 8;
  195.   GetChunkID(buffer,tempstr);
  196.   strcpy(typestr,tempstr); // save file type
  197.   if ((strcmp(tempstr,"ILBM")!=0) && (strcmp(tempstr,"PBM ")!=0) )
  198.     errout("This isn't an ILBM format file!");
  199.  
  200.   /*
  201.   ** point to BMHD chunk, the first NORMAL chunk!
  202.   */
  203.  
  204.   buffer += 4;
  205.   GetChunkID(buffer,tempstr);
  206.   if (strcmp(tempstr,"BMHD")!=0)
  207.     errout("What kind of ILBM is this? There's no BMHD chunk!");
  208.  
  209.   return(buffer);
  210. }
  211.  
  212.  
  213.  
  214. void GetChunkID(char huge *buffer,char *tempstr)
  215. {
  216.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  217.   tempstr[4]=0;
  218. }
  219.  
  220.  
  221.  
  222.  
  223. int NextChunkID(char huge *buffer)
  224. {
  225.   unsigned int newoffset;
  226.  
  227.   newoffset = (*(buffer+7)&0xFF) + (*(buffer+6)*256);
  228.   if ((newoffset & 1)==1) newoffset += 1;
  229.   return(newoffset+8); /* +8 because chunk + offset = 8 bytes! */
  230. }
  231.  
  232.  
  233. /////////////////////////////////////////////////////////////
  234. /*
  235. ** CGA loader
  236. */
  237. /////////////////////////////////////////////////////////////
  238. void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem)
  239. {
  240.  unsigned int bpwidth,loopY,loopX,loopB,offset,data;
  241.  char huge *screen,b1,b2,unpacked[1280];
  242.  
  243.  bpwidth = width/8;
  244.  
  245.  for (loopY=0;loopY<height;loopY++)
  246.      {
  247.       if (compress==1)
  248.      buffer=Decompress(buffer,unpacked,bpwidth,planes);
  249.  
  250.       offset=0;
  251.       screen=scrnmem+(loopY*((width/8)*planes));
  252.       // screen = MK_FP(0xb800,(0x2000*(loopY&1))+(80*(loopY/2)));
  253.       for (loopX=0;loopX<bpwidth;loopX++)
  254.       {
  255.        if (compress==1)
  256.           {
  257.            b1 = *(unpacked+offset);
  258.            b2 = *(unpacked+bpwidth+offset);
  259.           }
  260.        else
  261.           {
  262.            b1 = *(buffer+offset);
  263.            b2 = *(buffer+bpwidth+offset);
  264.           }
  265.        offset++;
  266.  
  267.        // This loop should be in INLINE(!) assembler!
  268.  
  269.                 asm       mov   cx,8
  270.                 asm       mov   bh,b1
  271.                 asm       mov   bl,b2
  272.                 asm       xor   dx,dx
  273.                 LoopTop:
  274.                 asm       test  bh,1
  275.                 asm       jz    NoOR
  276.                 asm       or    dx,4000h
  277.                 NoOR:
  278.                 asm       test  bl,1
  279.                 asm       jz    NoOR1
  280.                 asm       or    dx,8000h
  281.                 NoOR1:
  282.                 asm       cmp   cx,1
  283.                 asm       je    NoShift
  284.                 asm       shr   dx,1
  285.                 asm       shr   dx,1
  286.                 NoShift:
  287.                 asm       shr   bh,1
  288.                 asm       shr   bl,1
  289.                 asm       loop  LoopTop
  290.  
  291.                 asm       mov   data,dx
  292.  
  293.        /* first draft of above loop:
  294.  
  295.            for (loopB=0;loopB<8;loopB++)
  296.                {
  297.                 if (b1 & 1==1) data |= 0x4000;
  298.                 if (b2 & 1==1) data |= 0x8000;
  299.                 if (loopB<7) data >>= 2;
  300.                 b1 >>= 1;
  301.                 b2 >>= 1;
  302.                }
  303.            */
  304.  
  305.            *screen = data >> 8;
  306.            *(screen+1) = data;
  307.            screen += 2;
  308.           }
  309.  
  310.       if (!compress)
  311.          buffer += bpwidth*planes;
  312.      }
  313. }
  314.  
  315.  
  316. /////////////////////////////////////////////////////////////
  317. //
  318. // EGA loader
  319. //
  320. /////////////////////////////////////////////////////////////
  321. void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem)
  322. {
  323.  unsigned bpwidth,loopY,loopX,loopB,offset,data,dest,j;
  324.  char huge *screen,b1,b2,unpacked[1280], // 8 screens wide max!!!
  325.       huge *plane[4];
  326.  long size;
  327.  
  328.  
  329.  bpwidth = width/8;
  330.  size=bpwidth*height;
  331.  
  332.  plane[0]=scrnmem;
  333.  plane[1]=plane[0]+size;
  334.  plane[2]=plane[1]+size;
  335.  plane[3]=plane[2]+size;
  336.  
  337.  for (loopY=0;loopY<height;loopY++)
  338.      {
  339.       if (compress==1)
  340.      {
  341.       buffer=Decompress(buffer,unpacked,bpwidth,planes);
  342.       dest=loopY*bpwidth;
  343.       for (i=0;i<4;i++)
  344.         {
  345.          movedata(FP_SEG(unpacked+bpwidth*i),
  346.               FP_OFF(unpacked+bpwidth*i),
  347.               FP_SEG(plane[i])+dest/16,
  348.               FP_OFF(plane[i])+(dest&15),
  349.               bpwidth);
  350.         }
  351.      }
  352.       else
  353.      {
  354.       dest=loopY*bpwidth;
  355.       for (i=0;i<4;i++)
  356.         {
  357.          movedata(FP_SEG(buffer+bpwidth*i),FP_OFF(buffer+bpwidth*i),
  358.               FP_SEG(plane[i])+dest/16,FP_OFF(plane[i])+(dest&15),
  359.               bpwidth);
  360.         }
  361.       buffer += bpwidth*planes;
  362.      }
  363.      }
  364. }
  365.  
  366. /////////////////////////////////////////////////////////////
  367. /*
  368. ** MCGA loader
  369. */
  370. /////////////////////////////////////////////////////////////
  371. void Do_MCGA_Screen(char huge *buffer,char compress,int width,int height,char huge *scrnmem)
  372. {
  373.  unsigned int bpwidth,loopY,loopX,loopB,offset,data;
  374.  char huge *screen,b1,b2,unpacked1[1280],unpacked[1280];
  375.  
  376.  
  377.  screen=scrnmem;
  378.  
  379.  for (loopY=0;loopY<height;loopY++)
  380.      {
  381.       if (compress==1)
  382.          {
  383.       buffer=Decompress(buffer,unpacked,width,1);
  384.       if (strcmp(typestr,"ILBM")==0)
  385.          {
  386.           int tloop;
  387.  
  388.           memset(unpacked1,0,320);
  389.           for (tloop=0;tloop<40;tloop++)
  390.           {
  391.            int tloop1,tloop2;
  392.            unsigned char mask[8] = { 0x80,0x40,0x20,0x10,8,4,2,1 };
  393.  
  394.            for (tloop1=0;tloop1<8;tloop1++)
  395.              for (tloop2=0;tloop2<8;tloop2++)
  396.                unpacked1[tloop*8+tloop1]|=
  397.               ((( (unsigned)unpacked[tloop+(7-tloop2)*40]
  398.               &mask[tloop1])
  399.               <<tloop1)
  400.               >>tloop2);
  401.           }
  402.           movedata(_DS,(unsigned)unpacked1,FP_SEG(screen),FP_OFF(screen),width);
  403.          }
  404.       else movedata(_DS,(unsigned)unpacked,FP_SEG(screen),FP_OFF(screen),width);
  405.          }
  406.       else
  407.          {
  408.       movedata(FP_SEG(buffer),FP_OFF(buffer),FP_SEG(screen),FP_OFF(screen),width);
  409.           buffer += width;
  410.          }
  411.       screen+=width;
  412.      }
  413. }
  414.  
  415. /////////////////////////////////////////////////////////////
  416. /*
  417. ** ILBM's RLE decompressor. Merely pass the address of the compressed
  418. ** ILBM bitplane data, where to unpack it, the # of bytes each bitplane
  419. ** takes up, and the # of bit planes to unpack.
  420. */
  421. /////////////////////////////////////////////////////////////
  422. void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes)
  423. {
  424.  int count,offset,loopP;
  425.  unsigned char byte,rept;
  426.  
  427.  #if 0
  428.  for (loopP=0;loopP<planes;loopP++)
  429.      {
  430.       count = 0;
  431.  
  432.       do {
  433.           rept = *(buffer);
  434.           if (rept > 0x80)
  435.              {
  436.               rept = (rept^0xff)+2;
  437.               byte = *(buffer+1);
  438.               buffer+=2;
  439.  
  440.               memset(unpacked,byte,rept);
  441.              }
  442.           else if (rept < 0x80)
  443.              {
  444.           rept++;
  445.           movedata(FP_SEG(buffer),FP_OFF(buffer)+1,_DS,(unsigned) unpacked,rept);
  446.           buffer += rept+1;
  447.              }
  448.           count += rept;
  449.           unpacked += rept;
  450.  
  451.          } while (count<bpwidth);
  452.      }
  453.  #else
  454.  
  455.  unsigned PackHi,PackLo,BufHi,BufLo;
  456.  
  457.  PackHi=FP_SEG(unpacked);
  458.  PackLo=FP_OFF(unpacked);
  459.  BufHi=FP_SEG(buffer);
  460.  BufLo=FP_OFF(buffer);
  461.  
  462.  asm    push    di
  463.  asm    push    si
  464.  asm    push    ds
  465.  
  466.  asm    mov    es,PackHi
  467.  asm    mov    di,PackLo
  468.  asm    mov    ds,BufHi
  469.  asm    mov    si,BufLo
  470.  asm    mov    cl,planes
  471.  asm    xor    ch,ch
  472.  asm    xor    ah,ah
  473.  LOOP1:
  474.  asm    push    cx
  475.  asm    xor    dx,dx        // DX = count
  476.  
  477.  LOOP2:
  478.  asm    lodsb
  479.  asm    cmp    al,0x80
  480.  asm    jbe    L2
  481.  asm    xor    al,0xff        // rept^0xff
  482.  asm    add    al,2        // rept+=2
  483.  asm    add    dx,ax
  484.  asm    mov    cl,al
  485.  asm    xor    ch,ch
  486.  asm    lodsb                // AL=byte to rept
  487.  asm    rep stosb        // repeat it!
  488.  asm    jmp    L3
  489.  
  490.  L2:
  491.  asm    inc    al
  492.  asm    add    dx,ax
  493.  asm    mov    cl,al
  494.  asm    xor    ch,ch
  495.  asm    rep movsb
  496.  
  497.  L3:
  498.  asm    cmp    dx,bpwidth
  499.  asm    jb    LOOP2
  500.  
  501.  asm    pop    cx
  502.  asm    loop    LOOP1
  503.  
  504.  asm    mov    PackHi,es
  505.  asm    mov    PackLo,di
  506.  asm    mov    BufHi,ds
  507.  asm    mov    BufLo,si
  508.  
  509.  asm    pop    ds
  510.  asm    pop    si
  511.  asm    pop    di
  512.  
  513.  buffer=MK_FP(BufHi,BufLo);
  514.  unpacked=(char *)PackLo;
  515.  #endif
  516.  
  517.  return(buffer);
  518. }
  519.  
  520.  
  521. #if 0
  522. /////////////////////////////////////////////////////////////
  523. //
  524. // move an EGA bitplane
  525. //
  526. /////////////////////////////////////////////////////////////
  527. void EGA_MoveBitplane(char huge *from,char far *to,int bpwidth)
  528. {
  529.  unsigned width;
  530.  
  531. asm        push    ds
  532. asm        push    di
  533. asm        push    si
  534.  
  535. asm        lds    si,from        //;DS:SI = from buffer
  536. asm        les    di,to        //;ES:DI = screen
  537. asm        mov    bx,bpwidth
  538. asm        mov    width,bx
  539.  
  540. asm        mov    dx,SCindex    //;start writing to SCmapmask register
  541. asm        mov    al,SCmapmask
  542. asm        out    dx,al
  543. asm        inc    dx
  544.  
  545. asm        mov    bh,4        //;4 bitplanes!
  546. asm        mov    ah,1        //;start at bitplane 0
  547.  
  548. EGA1:
  549.  
  550. asm        mov    al,ah        //;select bitplane
  551. asm        out    dx,al
  552.  
  553. asm        xor    ch,ch
  554. asm        mov    cl,bl        //;cx = bitplane width
  555. asm        rep movsb
  556. asm        sub    di,width    //;start at beginnin' of line again...
  557. asm        shl    ah,1
  558. asm        dec    bh
  559. asm        jnz    EGA1
  560.  
  561. asm        mov    al,15
  562. asm        out    dx,al        //;write to ALL bitplanes again
  563.  
  564. asm        pop    si
  565. asm        pop    di
  566. asm        pop    ds
  567. }
  568. #endif
  569.  
  570.  
  571.